// Bristleback plugin - Copyright (c) 2010 bristleback.googlecode.com
// ---------------------------------------------------------------------------
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
// This library is distributed in the hope that it will be useful,
// but without any warranty; without even the implied warranty of merchantability
// or fitness for a particular purpose.
// You should have received a copy of the GNU Lesser General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>.
// ---------------------------------------------------------------------------
package pl.bristleback.server.bristle.actions;

import org.apache.log4j.Logger;
import pl.bristleback.server.bristle.config.ActionAnnotationsProcessor;
import pl.bristleback.server.bristle.config.BristleConfiguration;
import pl.bristleback.server.bristle.exceptions.BristleRuntimeException;

import java.util.List;

/**
 * Helper class used to retrieve annotated actions, opaqued in {@link ActionsContainer} object and to inject Spring dependencies.
 * <p/>
 * Actions annotations processor instance is taken from configuration, its method is invoked and returns list of action class information.
 * Finally, every action class is checked. If any action class is set to have only one instance,
 * that instance is initialized using {@link pl.bristleback.server.bristle.actions.ActionInstanceCreator}.
 * <p/>
 * Created on: 2010-10-04 17:15:29 <br/>
 *
 * @author Wojciech Niemiec
 */
public final class ActionsInitializer {
  private static Logger log = Logger.getLogger(ActionsInitializer.class.getName());

  private ActionInstanceCreator actionInstanceCreator = new ActionInstanceCreator();
  private ActionsContainer container;

  /**
   * Gets previously created actions container. Returns null if container was not created yet.
   *
   * @return actions container.
   */
  public ActionsContainer getContainer() {
    return container;
  }

  /**
   * Loads actions using {@link ActionAnnotationsProcessor} implementation.
   * Implementation of action annotations processor can be specified by user by setting plugin property with name given in
   * {@link pl.bristleback.server.bristle.config.BristleConfigurationElement#ACTION_ANNOTATION_PROCESSOR} enum.
   *
   *
   * @param configuration plugin configuration.
   */
  public void loadActionsContainer(BristleConfiguration configuration) {
    initialize();
    loadActionsByResolver(configuration);
  }

  private void initialize() {
    if (container != null) {
      throw new BristleRuntimeException("actions already initialized");
    }
    container = new ActionsContainer();
  }

  private void loadActionsByResolver(BristleConfiguration configuration) {
    ActionAnnotationsProcessor actionAnnotationsProcessor = configuration.getAnnotationProcessor();
    List<RemoteActionInformation> actions = actionAnnotationsProcessor.getAnnotatedActions(configuration);
    for (RemoteActionInformation action : actions) {
      addAction(action);
      createActionInstance(action);
    }
  }

  private void addAction(RemoteActionInformation actionInformation) {
    if (container.getAction(actionInformation.getActionName()) != null) {
      throw new BristleRuntimeException("action class with name " + actionInformation.getActionName() + "is already registered.");
    }
    container.addAction(actionInformation);
  }

  private void createActionInstance(RemoteActionInformation actionInformation) {
    if (actionInformation.isSingleton()) {
      RemoteAction remoteAction = actionInstanceCreator.createInstance(actionInformation);
      actionInformation.setAction(remoteAction);
    }
  }
}
